package com.tos.second.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.tos.second.common.Result.PageResult;
import com.tos.second.common.basecontext.BaseContext;
import com.tos.second.common.constant.MessageConstant;
import com.tos.second.common.exception.*;
import com.tos.second.dto.*;
import com.tos.second.entity.User;
import com.tos.second.mapper.UserMapper;
import com.tos.second.service.UserService;
import com.tos.second.vo.UserLoginVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;

@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;

    /**
     * 用户登录
     *
     * @param userLoginDto
     * @return
     */
    @Override
    public UserLoginVo login(UserLoginDto userLoginDto) {
        //有验证码代码：
        String username = userLoginDto.getUsername();
        //数据库的用户
        User dUser = userMapper.getOne(username);
        if (dUser == null) {
            throw new LoginFailedException(MessageConstant.ACCOUNT_NOT_FOUND);
        }
        // 如果查询到用户，先查询用户的状态，如果为0则禁止登录
        if (dUser.getStatus() == 0) {
            throw new LoginFailedException(MessageConstant.ACCOUNT_LOCKED);
        }
        // 如果不为空，则比对密码
        String password = userLoginDto.getPassword();
        //将密码进行md5加密
        password = DigestUtils.md5DigestAsHex(password.getBytes());
        if (!dUser.getPassword().equals(password)) {
            throw new LoginFailedException(MessageConstant.PASSWORD_ERROR);
        }
        // 取出前端验证码
        String fCode = userLoginDto.getCaptcha();
        if (fCode == null) {
            throw new BaseException(MessageConstant.CODE_NOT_NULL);
        }
        // 组装redisKey获得redis中存储的验证码
        String redisKey = MessageConstant.REDIS_KEY_CHECK_CODE + userLoginDto.getCheckCodeKey();
        String bCode = (String) redisTemplate.opsForValue().get(redisKey);
        if (bCode == null) {
            throw new BaseException(MessageConstant.CODE_NULL);
        }
        //校验验证码
        if (!bCode.equalsIgnoreCase(fCode)){
            // 失败的话删除验证码
            redisTemplate.delete(redisKey);
            throw new BaseException(MessageConstant.CODE_ERROR);
        }

        //删除验证码
        redisTemplate.delete(redisKey);
        //全部校验完成，返回用户信息
        UserLoginVo userLoginVo = new UserLoginVo();
        BeanUtils.copyProperties(dUser, userLoginVo);
        return userLoginVo;





//        // 无验证码代码：
//        String username = userLoginDto.getUsername();
////        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
////        queryWrapper.eq(User::getUsername, username);
////        //由于进行了唯一，所以查询一个即可
////        User user = getOne(queryWrapper);
//        User user = userMapper.getOne(username);
//        //如果查询不到用户，则返回报错
//        if (user == null) {
//            throw new LoginFailedException(MessageConstant.ACCOUNT_NOT_FOUND);
//        }
//        // 如果查询到用户，先查询用户的状态，如果为0则禁止登录
//        if (user.getStatus() == 0) {
//            throw new LoginFailedException(MessageConstant.ACCOUNT_LOCKED);
//        }
//        // 如果不为空，则比对密码
//        String password = userLoginDto.getPassword();
//        //将密码进行md5加密
//        password = DigestUtils.md5DigestAsHex(password.getBytes());
//        if (!user.getPassword().equals(password)) {
//            throw new LoginFailedException(MessageConstant.PASSWORD_ERROR);
//        }
//        //全部正确后即可登录返回用户信息
//        //将用户信息返回
//        UserLoginVo userLoginVo = new UserLoginVo();
//        BeanUtils.copyProperties(user, userLoginVo);
//        return userLoginVo;
    }

    /**
     * 用户注册接口
     *
     * @param userRegisterDto
     */
    @Override
    public void register(UserRegisterDto userRegisterDto) {
        User user = new User();
        //比对验证码
        //1.获得前端传过来的验证码
        String code = userRegisterDto.getCode();
        //判断验证码是否存在
        if (code != null) {
            //2.获取redis中的验证码
            String checkCode = (String) redisTemplate.opsForValue().get(userRegisterDto.getEmail());
            log.info("code:{}", code);
            log.info("checkCode:{}", checkCode);
            if (checkCode != null && checkCode.equalsIgnoreCase(code)) {
                BeanUtils.copyProperties(userRegisterDto, user);
                //将密码进行md5加密
                user.setPassword(DigestUtils.md5DigestAsHex(user.getPassword().getBytes()));
                //添加用户即可
                user.setCreateTime(LocalDateTime.now());
                user.setUpdateTime(LocalDateTime.now());
                //去除掉redis中的验证码
                userMapper.saveUser(user);
                redisTemplate.delete(userRegisterDto.getEmail());
            } else {
                throw new RegisterException(MessageConstant.CODE_ERROR);
            }
        }
    }

    /**
     * 用户修改密码接口
     *
     * @param userChangePasswordDto
     */
    @Override
    public void changePassword(UserChangePasswordDto userChangePasswordDto) {
        //获取前端传过来的用户名查询数据库
        String username = userChangePasswordDto.getUsername();
//        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
//        queryWrapper.eq(User::getUsername, username);
//        User user = getOne(queryWrapper);
        User user = userMapper.getOne(username);
        //获取user的邮箱
        String email = user.getEmail();
        //比对前端传过来的邮箱
        if (!email.equals(userChangePasswordDto.getEmail())) {
            throw new PasswordEditFailedException(MessageConstant.EMAIL_ERROR);
        }
        //比前端传过来的验证码
        String code = userChangePasswordDto.getCode();
        // redis中的验证码
        String checkCode = (String) redisTemplate.opsForValue().get(email);
        if (!code.equalsIgnoreCase(checkCode)) {
            throw new PasswordEditFailedException(MessageConstant.CODE_ERROR);
        }
        //当验证码正确后，修改密码
        user.setPassword(DigestUtils.md5DigestAsHex(userChangePasswordDto.getNewPassword().getBytes()));
        //删除redis中的验证码
        redisTemplate.delete(email);
        //修改数据库
        userMapper.updateUser(user);
//        updateById(user);
    }

    @Override
    public void editUser(UserEditDto userEditDto) {
        //获取当前用户id
        Long currentId = BaseContext.getCurrentId();
        //获取数据库中用户信息
        User user = getById(currentId);
        //获取验证码
        String code = userEditDto.getCode();
        //redis中的code
        String checkCode = (String) redisTemplate.opsForValue().get(user.getEmail());
        //比对成功
        if (code.equalsIgnoreCase(checkCode)){
            String password = user.getPassword();

            //复制属性
            BeanUtils.copyProperties(userEditDto, user);
            //加密密码
            if (userEditDto.getPassword() != null){
                user.setPassword(DigestUtils.md5DigestAsHex(userEditDto.getPassword().getBytes()));
            }
            else {
                user.setPassword(password);
            }

            //更新
            userMapper.updateUser(user);
            //删除验证码
            redisTemplate.delete(user.getEmail());
        }
        else {
            //比对失败
            throw new PasswordEditFailedException(MessageConstant.CODE_ERROR);
        }


//        updateById(user);
    }

    /**
     * 充值
     * @param money
     */
    @Override
    public void charge(BigDecimal money) {
        //获取登录用户id
        Long currentId = BaseContext.getCurrentId();
        if (currentId == null){
            throw new UserNotLoginException(MessageConstant.USER_NOT_LOGIN);
        }
        //判断金额是否为空或者小于等于0
        if (money == null || money.compareTo(BigDecimal.ZERO) <= 0){
            throw new BaseException(MessageConstant.MONEY_NOT_ENOUGH);
        }
        //根据id获得用户信息
        User user = userMapper.getById(currentId);
        //判断用户是否存在
        if (user == null){
            throw new UserNotLoginException(MessageConstant.USER_NOT_LOGIN);
        }
        //判断用户的状态
        if (user.getStatus() == 0){
            throw new BaseException(MessageConstant.ACCOUNT_LOCKED);
        }
        //判断传的金额是否过大
        if (money.compareTo(new BigDecimal(99999)) > 0){
            throw new BaseException(MessageConstant.MONEY_IS_TO_LARGE);
        }
        if (user.getBalance().add(money).compareTo(BigDecimal.valueOf(Math.pow(10, 38))) > 0){
            throw new BaseException(MessageConstant.USER_MONEY_IS_TO_LARGE);
        }
        //增加余额
        user.setBalance(user.getBalance().add(money));
        //更新用户
        userMapper.updateUser(user);
    }
}
